﻿using System.Collections.Generic;
using System.Linq;


namespace DixitOnline.DixitGame
{
    public enum GameStatus {InProgress, Paused, Finished}

	public class Game
	{
		#region Fields and properties


		///TODO: Implement check for max player count in setter
		/// <summary>
		/// all players
		/// </summary>
		public List<Player> Players { get; private set; }

		
		public List<Card> CardPack { get; private set; }

		public Player CurrentPlayer { get; private set; }

		#endregion Fields and properties


		#region Public Methods

		public void Start()
		{
			initGame();


			// Main game cycle

			while (CardPack.Count() != CardPack.Where(c => c.Status == CardStatus.Out).Count())
			{
				foreach (var player in Players.OrderBy(p => p.Order))
				{
					Card playingCard = player.PlayCard();
					CardPack.Single(c => c == playingCard).Status = CardStatus.OnDesc;
					Association association = player.ShareAssociation();
					foreach (Player otherPlayer in Players.Where(p => p!= player))
					{
						/// TODO: Implement logic of further game
						/// 1. Other players play their cards
						/// 2. Players vote for the cards
						/// 3. Calculating scores etc
						/// 4. Moving cards out
						/// 5. Taking new cards
						/// 6. Implement two different cycles
					}
				}
			}

		}


		public void Finish()
		{
		}

		public void Pause()
		{
		}

		/// <summary>
		/// Marks player who makes the step, as current
		/// </summary>
		/// <param name="player">new current player</param>
		public void SetCurrentPlayer(Player player)
		{
			CurrentPlayer = player;
			///TODO: Probably will need to have an additional boolean property for the player e.g. IsCurrent
			/// In this case we will need to set IsCurrent = false for the previous player here
		}

		public void AddPlayer (Player player)
		{
			Players.Add(player);
		}

		#endregion Public Methods


		#region Private methods
		private void initGame()
		{
			checkPlayersCount();

			CardPack = initCardPack();

			giveCards();

		}

		/// <summary>
		/// Give cards to players
		/// </summary>
		private void giveCards()
		{
			foreach (var player in Players)
			{
				IEnumerable<Card> playerCards = CardPack.PickRandom(Consts.PlayerCardsCount);
				player.Cards.AddRange(playerCards);
				CardPack.Intersect(playerCards).ForEach(c => c.Status = CardStatus.OnHands);
			}
		}

		private void checkPlayersCount()
		{
			/// TODO: Check min and max player count before game start
			/// if it doesn't match - raise an exception
		}

		private List<Card> initCardPack()
		{
			/// TODO: Create new card pack
			/// Do not forget about card status initialization

			return null;
		}

		#endregion Private methods
	}
}
